package com.zx.ishopping.services.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zx.ishopping.Constants.*;
import com.zx.ishopping.DTO.*;

import com.zx.ishopping.VO.LoginVo;
import com.zx.ishopping.VO.UserVo;
import com.zx.ishopping.entity.Cart;
import com.zx.ishopping.entity.User;
import com.zx.ishopping.exceptions.LoginFailException;
import com.zx.ishopping.exceptions.RegisterFailException;
import com.zx.ishopping.exceptions.UserFailException;
import com.zx.ishopping.mapper.CartMapper;
import com.zx.ishopping.mapper.UserMapper;
import com.zx.ishopping.results.PageResult;
import com.zx.ishopping.results.Result;
import com.zx.ishopping.services.UserService;
import com.zx.ishopping.utils.JwtUtil;
import com.zx.ishopping.utils.Md5Util;
import com.zx.ishopping.utils.ThreadLocalUtil;
import com.zx.ishopping.utils.VerificationCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;

import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private VerificationCodeUtil verificationCodeUtil;
    @Autowired
    private CartMapper cartMapper;
   

    /**
     * 登陆服务实现
     */
    @Override
    public LoginVo login(UserLoginDTO userLoginDto) {
       
        User user = userMapper.getUserByUserName(userLoginDto.getUsername());
        //判断该用户是否为空
        if (user == null){
            throw new LoginFailException(LoginConstant.USER_NOT_EXIST);
        }
        //对密码进行加密
        String md5String = Md5Util.getMD5String(userLoginDto.getPassword());
        if (!md5String.equals(user.getPassword())){
            throw new LoginFailException(LoginConstant.USER_PASSWORD_ERROR);
        }
        log.info("用户登陆成功,欢迎：{}",user.getUsername());
        //创建生成token令牌
        Map<String,Object> claims = new HashMap<>();
        claims.put("username",user.getUsername());
        claims.put("id",user.getId());
        String token = JwtUtil.getToken(claims);
        log.info("用户token令牌:{}",token);
        //登陆成功后，把当前用户id保存到threadLocal中；
        ThreadLocalUtil.set(user.getId());
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setRole(user.getRole());
        return loginVo;


    }

    /**
     * 用户注册，以及管理员添加用户
     * @param userInfoDTO
     */
    @Override
    public void register(UserInfoDTO userInfoDTO) {

        User user = new User();
        BeanUtils.copyProperties(userInfoDTO, user);
        commonUserRegister(user);
        
    }

    /**
     * 员工信息分页查询
     * @return
     */
    @Override
    public PageResult pageQuery(UserPageQueryDTO userPageQueryDTO) {
        PageHelper.startPage(userPageQueryDTO.getPage(), userPageQueryDTO.getPageSize());
        Page<UserVo> page = userMapper.pageQuery(userPageQueryDTO);
        long total = page.getTotal();
        List<UserVo> result = page.getResult();
        PageResult pageResult = new PageResult();
        pageResult.setTotal(total);
        pageResult.setData(result);
        log.info("查询到员工数据的数量为：{}",total);
        return pageResult;
    }

    /**
     * 管理员修改用户信息
     * 
     * @param userInfoDTO
     */
    @Override
    public void update(UserInfoDTO userInfoDTO) {

        User user = new User();
        BeanUtils.copyProperties(userInfoDTO, user);
        
        //根据id获取用户信息
        UserVo userById = userMapper.getUserById(user.getId());
        //判断用户名是否重复
        if (!user.getUsername().equals(userById.getUsername()) ){

            User userByUserName = userMapper.getUserByUserName(user.getUsername());
            if (userByUserName != null  ){
                log.info("重复的用户为{}",userByUserName);
                throw new UserFailException(UpdateConstant.USER_NAME_HAS_EXIST);
            }
        }

        //判断邮箱是否重复
        log.info("邮箱为{}",user.getEmail());
        if (!user.getEmail().equals(userById.getEmail())){
            User userByEmail = userMapper.getUserByEmail(user.getEmail());
            if (userByEmail != null){
                log.info("重复的邮箱{}",userByEmail);
                throw new UserFailException(UpdateConstant.EMAIL_HAS_EXIST);
            }
        }


        if (user.getPassword() != null){
            
            String md5String = Md5Util.getMD5String(user.getPassword());
            user.setPassword(md5String);
        }
        
        userMapper.update(user);

    }

    /**
     * 根据用户id查询用户信息
     *
     * @param id
     * @return
     */
    @Override
    public UserVo getUserById(Long id) {
     UserVo userVo =  userMapper.getUserById(id);
     return userVo;
    }

    /**
     * 删除用户
     * @param id
     */

    @Transactional
    @Override
    public void deleteUser(long id) {
        UserVo userVo = userMapper.getUserById(id);
        if(userVo.getRole() == 1){
            throw  new UserFailException(DeleteConstant.USER_IS_ADMIN);
        }
        //删除用户对应购物车以及其中内容
        
        userMapper.deleteUser(id);
    }

    /**
     * 发送验证码
     * @param email
     */
    @Override
    public void sendAndStoreCaptcha(String email) {
        //生成验证码
        String code = verificationCodeUtil.generateVerificationCode();
        //发送验证码
        verificationCodeUtil.sendVerificationCode(email, code);
        //存储验证码
        verificationCodeUtil.storeVerificationCode(email, code);
    }

    /**
     * 用户注册
     * @param userRegisterDTO
     */
    @Transactional
    @Override
    public void UserRegister(UserRegisterDTO userRegisterDTO) {
      log.info("邮箱{}，验证码{}",userRegisterDTO.getEmail(),userRegisterDTO.getCode());  
        //从redis中获取验证码,同时比较
        verificationCodeUtil.verifyCode(userRegisterDTO.getEmail(), userRegisterDTO.getCode());
        User user = new User();
        BeanUtils.copyProperties(userRegisterDTO, user);
        commonUserRegister(user);
        
        
    }

    /**
     * 验证码校验，同时判断邮箱是否存在
     * @param inputCode
     * @return
     */
    @Override
    public Boolean validateCaptcha(String inputCode,String  email) {
        
        //通过邮箱查找用户
        User user = userMapper.getUserByEmail(email);
        if (user == null){
            throw new UserFailException(GetConstant.USER_NOT_EXIST);
        }
        
        Boolean res = verificationCodeUtil.verifyCode(email,inputCode);
        return res;
    }

    /**
     * 忘记密码
     * @param userChangePasswordDTO
     */
    @Override
    public void forgetPassword(UserChangePasswordDTO userChangePasswordDTO) {
        
        
        
        //判断两次输入密码是否相同
        //相同代码向下运行，不相同抛出异常
        chackPassword(userChangePasswordDTO);

        //对密码进行加密
        String md5String = Md5Util.getMD5String(userChangePasswordDTO.getNewPassword());
        userChangePasswordDTO.setNewPassword(md5String);
        //忘记密码,通过邮箱设置新密码
        userMapper.changePassword(userChangePasswordDTO);
    }

    /**
     * 用户主动修改密码
     */
    @Override
    public void changePassword(UserChangePasswordDTO userChangePasswordDTO) {
        //判断用户是否输入了完整信息
        if (userChangePasswordDTO.getOldPassword() == null || userChangePasswordDTO.getNewPassword() == null || userChangePasswordDTO.getConfirmPassword() == null){
            throw new UserFailException(UpdateConstant.USER_INFO_IS_NULL);
        }
        //通过邮箱获取用户信息
        Long id =  ThreadLocalUtil.get();
        userChangePasswordDTO.setId(id);
        log.info("修改密码用户id{}",id);
        String oldPassword= userMapper.getPassword(id);
       
        
        //判断旧密码是否正确
        if (!oldPassword.equals(Md5Util.getMD5String(userChangePasswordDTO.getOldPassword()))){
            throw new UserFailException(UpdateConstant.PASSWORD_ERROR);
        }

        //判断新旧密码是否相同
        if (oldPassword.equals(Md5Util.getMD5String(userChangePasswordDTO.getNewPassword()))){
            throw new UserFailException(UpdateConstant.SAME_PASSWORD);
        }
        //判断两次输入密码是否相同
        chackPassword(userChangePasswordDTO);
        //对新密码进行加密
        String md5String = Md5Util.getMD5String(userChangePasswordDTO.getNewPassword());
        
        userChangePasswordDTO.setNewPassword(md5String);
        log.info("新密码{}",userChangePasswordDTO);
        userMapper.changePasswordById(userChangePasswordDTO);
        
        
        
    }

    /**
     * 用户修改信息
     * @param userInfoDTO
     */
    @Override
    public void updateUserInfo(UserInfoDTO userInfoDTO) {
        User user = new User();
        BeanUtils.copyProperties(userInfoDTO, user);
        user.setId(ThreadLocalUtil.get());
        //判断输入的内容
        if (userInfoDTO.getUsername() != null){
            //更新用户名
            userMapper.update(user);
        }
        
        if (userInfoDTO.getEmail() != null){
            //根据新邮箱查询数据库
            User userByEmail = userMapper.getUserByEmail(user.getEmail());
            if (userByEmail != null){
                //邮箱已存在
                throw new UserFailException(UpdateConstant.EMAIL_HAS_EXIST);
            }else {
                //更新邮箱
                userMapper.update(user);
            }
        }
    }


    /**
     * 注册业务
     * @param user
     */
    public void commonUserRegister(User user) {
        //进行注册业务
        if (user.getPassword() == null || user.getUsername() == null || user.getEmail() == null){
            throw new UserFailException(RegisterConstant.USER_INFO_IS_NULL);
        }

        User userByUserName = userMapper.getUserByUserName(user.getUsername());
        if (userByUserName != null){
            throw new UserFailException(RegisterConstant.USER_NAME_EXIST);
        }
        User userByEmail = userMapper.getUserByEmail(user.getEmail());
        if (userByEmail != null){
            throw new UserFailException(RegisterConstant.USER_EMAIL_EXIST);
        }

        String password = Md5Util.getMD5String(user.getPassword());
        user.setPassword(password);

        user.setRole(2);
        userMapper.inset(user);
        log.info("用户注册成功,用户名：{}",user.getUsername());
        //同时生成新用户的购物车
        Cart cart = new Cart();
        cart.setUserId(user.getId());
        cart.setQuantity(0);
        cart.setTotalPrice(BigDecimal.valueOf(0));
        cartMapper.createCart(cart);
    }


    /**
     * 新密码和确认密码比对
     * @param userChangePasswordDTO
     * @return
     */
    public Boolean chackPassword(UserChangePasswordDTO userChangePasswordDTO){
        
        boolean flag = userChangePasswordDTO.getConfirmPassword().equals(userChangePasswordDTO.getNewPassword());
        log.info("新密码{}，确认密码{}",userChangePasswordDTO.getNewPassword(),userChangePasswordDTO.getConfirmPassword());
        if (!flag){
            throw new UserFailException(UpdateConstant.INCONSISTENT_PASSWORD);
        }
        return true;
    }
    
    
}
